home *** CD-ROM | disk | FTP | other *** search
/ Aminet 32 / Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso / Aminet / game / think / MUIMineSrc.lha / MUIMineSource / MFWindow.c < prev    next >
C/C++ Source or Header  |  1998-12-22  |  57KB  |  1,859 lines

  1. /*
  2.     MUI custom class for mine field window
  3. */
  4. #include "MUIMine.h"
  5. #include "MFStrings.h"
  6. #include "LevelData.h"
  7. #include "MFWindow.h"
  8. #include "BTWindow.h"
  9. #include "LEWindow.h"
  10. #include "ISWindow.h"
  11. #include "MineField.h"
  12. #include "FaceButton.h"
  13. #include "Digits.h"
  14.  
  15.  
  16. /*
  17.     instance data
  18. */
  19. struct MFWindowData
  20. {
  21.     struct NewMenu * NewMenus;  // NewMenu's for Menustrip
  22.     Object * FaceButton;        // window's 'Start Game' button
  23.     Object * MinesDisp;         // window's 'Mines Left' string
  24.     Object * TimeDisp;          // window's 'Time Taken' string
  25.     Object * MineField;         // window's minefield object
  26.     Object * MenuStrip;         // window's menus
  27.     Object * LevelMenu;         // Level menu
  28.     struct LevelDataList Levels;// level info
  29.     STRPTR   MineFieldImageFile;    // file name for minefield images
  30.     STRPTR   StartButtonImageFile;  // file name for start button images
  31.     STRPTR   MinesDigitsImageFile;  // file name for mines left digits images
  32.     STRPTR   TimeDigitsImageFile;   // file name for times taken digits images
  33.     ULONG    Options;           // option flags (see below for defs)
  34.     int      LastGameTime;      // time taken for the last succesfull game
  35.     ULONG    LevelMenuCheck;    // id of checked level menu item
  36.     Object * MUIAboutWindow;    // MUI about window object
  37.     char  LastBestTimeName[BT_NAME_SIZE];   // last best time name entered
  38. };
  39.  
  40.  
  41. /*
  42.     defines for difficulty levels
  43. */
  44. #define DEFAULT_LEVEL       MUIV_MFWindow_Level_Beginner
  45.  
  46. #define MAX_NUM_LEVELS      30
  47.  
  48. /*
  49.     defines for option flags
  50. */
  51. #define MFW_OPT_SAFESTART   0x00000001L     // first move in game always safe
  52.  
  53.  
  54. /*
  55.     global data items
  56. */
  57.  
  58. struct MUI_CustomClass *mccMineField  = NULL;
  59. struct MUI_CustomClass *mccFaceButton = NULL;
  60. struct MUI_CustomClass *mccDigits     = NULL;
  61. struct MUI_CustomClass *mccBTWindow   = NULL;
  62. struct MUI_CustomClass *mccLEWindow   = NULL;
  63. struct MUI_CustomClass *mccISWindow   = NULL;
  64.  
  65.  
  66. /*
  67.     window's menu data
  68. */
  69.  
  70. #define MENU_GAME           100
  71. #define MENU_GAME_START     101
  72. #define MENU_GAME_BESTTIMES 102
  73. #define MENU_GAME_LEVELS    103
  74. #define MENU_GAME_IMAGES    104
  75. #define MENU_GAME_SAFESTART 106
  76. #define MENU_GAME_INFO      110
  77. #define MENU_GAME_QUIT      199
  78. #define MENU_LEVEL          200
  79. #define MENU_LEVEL_BASE     201
  80. #define MENU_MUI            300
  81. #define MENU_MUI_ABOUT      301
  82. #define MENU_MUI_SETTINGS   302
  83.  
  84.  
  85. /*
  86.     default NewMenus for MFWindowNewMenu
  87. */
  88.  
  89. struct NewMenu MFWindowNewMenu[] =
  90. {
  91.     {NM_TITLE, (STRPTR)MSG_MENUTITLE_GAME,          NULL, 0, 0, (APTR)MENU_GAME},
  92.     { NM_ITEM, (STRPTR)MSG_MENUITEM_GAMESTART,      NULL, 0, 0, (APTR)MENU_GAME_START},
  93.     { NM_ITEM, NM_BARLABEL,                         NULL, 0, 0, NULL},
  94.     { NM_ITEM, (STRPTR)MSG_MENUITEM_GAMEBESTTIMES,  NULL, 0, 0, (APTR)MENU_GAME_BESTTIMES},
  95.     { NM_ITEM, NM_BARLABEL,                         NULL, 0, 0, NULL},
  96.     { NM_ITEM, (STRPTR)MSG_MENUITEM_GAMELEVELSETUP, NULL, 0, 0, (APTR)MENU_GAME_LEVELS},
  97.     { NM_ITEM, (STRPTR)MSG_MENUITEM_GAMEIMAGESETUP, NULL, 0, 0, (APTR)MENU_GAME_IMAGES},
  98.     { NM_ITEM, (STRPTR)MSG_MENUITEM_GAMESAFESTART,  NULL, CHECKIT | MENUTOGGLE, 0, (APTR)MENU_GAME_SAFESTART},
  99.     { NM_ITEM, NM_BARLABEL,                         NULL, 0, 0, NULL},
  100.     { NM_ITEM, (STRPTR)MSG_MENUITEM_GAMEINFO,       NULL, 0, 0, (APTR)MENU_GAME_INFO},
  101.     { NM_ITEM, NM_BARLABEL,                         NULL, 0, 0, NULL},
  102.     { NM_ITEM, (STRPTR)MSG_MENUITEM_GAMEQUIT,       NULL, 0, 0, (APTR)MENU_GAME_QUIT},
  103.     {NM_TITLE, (STRPTR)MSG_MENUTITLE_LEVEL,         NULL, 0, 0, (APTR)MENU_LEVEL},
  104.     {NM_TITLE, (STRPTR)MSG_MENUTITLE_MUI,           NULL, 0, 0, (APTR)MENU_MUI},
  105.     { NM_ITEM, (STRPTR)MSG_MENUITEM_MUIABOUT,       NULL, 0, 0, (APTR)MENU_MUI_ABOUT},
  106.     { NM_ITEM, (STRPTR)MSG_MENUITEM_MUISETTINGS,    NULL, 0, 0, (APTR)MENU_MUI_SETTINGS},
  107.     {NM_END,   NULL,                                NULL, 0, 0, NULL}
  108. };
  109.  
  110. /*
  111.     level menu comm keys
  112. */
  113. #define NUM_LEVEL_COMM_KEYS     10
  114. STRPTR LevelCommKeys[] =
  115. {
  116.     "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"
  117. };
  118.  
  119.  
  120.  
  121. /*
  122.     function prototypes
  123. */
  124.  
  125. static void SetLevel(Object * obj, struct MFWindowData * data, ULONG level);
  126. static void CheckBestTime(Object * obj, struct MFWindowData * data);
  127. static BOOL GetBestTimeName(Object * obj, struct LevelData * pLevel, int rank);
  128. static void ShowBestTimes(Object * obj, struct LevelDataList * lList, int hiRank);
  129. static void SetupLevels(Object *, struct MFWindowData * data);
  130. static void SetupImages(Object * obj, struct MFWindowData * data);
  131. static void ShowProgInfo(Object * obj);
  132.  
  133.  
  134. /*
  135.     function :    clears the existing Level menu by removing and disposing
  136.                   of all the menu's items
  137.  
  138.     parameters :  data = pointer to the MFWindow data
  139.  
  140.     return :      none
  141. */
  142. static void ClearLevelMenu(struct MFWindowData * data)
  143. {
  144.     /*
  145.         make sure we have a Level menu to play with
  146.     */
  147.     if (data->LevelMenu)
  148.     {
  149.         int i;
  150.         struct LevelData * pLevel = data->Levels.LevelList;
  151.  
  152.         for (i = data->Levels.NumLevels; i > 0; i--)
  153.         {
  154.             if (pLevel->MenuItem)
  155.             {
  156.                 DoMethod(data->LevelMenu, MUIM_Family_Remove, pLevel->MenuItem);
  157.                 MUI_DisposeObject(pLevel->MenuItem);
  158.                 pLevel->MenuItem = NULL;
  159.             }
  160.             pLevel->MenuId = 0;
  161.             pLevel++;
  162.         }
  163.     }
  164. }
  165.  
  166. /*
  167.     function :    builds the Level menu items from the LevelDataList and
  168.                   add them to the LevelMenu
  169.  
  170.     parameters :  data = pointer to the MFWindow data
  171.  
  172.     return :      none
  173. */
  174. static void BuildLevelMenu(struct MFWindowData * data)
  175. {
  176.     /*
  177.         make sure we have a Level menu to play with
  178.     */
  179.     if (data->LevelMenu)
  180.     {
  181.         int i, n;
  182.         ULONG menuId;
  183.         ULONG mxBit;
  184.         STRPTR commKey;
  185.         struct LevelData * pLevel;
  186.  
  187.         /*
  188.             make sure any existing Level menu items are removed
  189.         */
  190.         ClearLevelMenu(data);
  191.  
  192.         pLevel = data->Levels.LevelList;
  193.         menuId = MENU_LEVEL_BASE;
  194.         mxBit = 1;
  195.         for (n = 0, i = data->Levels.NumLevels; i > 0  &&  n < MAX_NUM_LEVELS; i--)
  196.         {
  197.             commKey = (n < NUM_LEVEL_COMM_KEYS) ? LevelCommKeys[n] : NULL;
  198.  
  199.             pLevel->MenuItem = MUI_MakeObject(MUIO_Menuitem, pLevel->Name,
  200.                                                 commKey, CHECKIT, menuId);
  201.             if (pLevel->MenuItem)
  202.             {
  203.                 pLevel->MenuId = menuId;
  204.                 SetAttrs(pLevel->MenuItem,
  205.                             MUIA_Menuitem_Exclude, (0x7FFFFFF & ~mxBit),
  206.                             TAG_DONE);
  207.                 DoMethod(data->LevelMenu, MUIM_Family_AddTail, pLevel->MenuItem);
  208.  
  209.                 n++;
  210.                 menuId++;
  211.                 mxBit = mxBit << 1;
  212.             }
  213.  
  214.             pLevel++;
  215.         }
  216.     }
  217. }
  218.  
  219.  
  220. /*
  221.     function :    create and initialize the NewMenu list for the window
  222.  
  223.     parameters :  none
  224.  
  225.     return :      pointer to the new menu structure
  226. */
  227. struct NewMenu * CreateNewMenus(void)
  228. {
  229.     int i, n;
  230.     struct NewMenu *nm, *pNewMenu;
  231.  
  232.     /*
  233.         determine the number of NewMenu entries that need to be allocated
  234.     */
  235.     n = sizeof(MFWindowNewMenu) / sizeof(struct NewMenu);
  236.  
  237.     /*
  238.         attempt to allocate the NewMenu array
  239.     */
  240.     if (!(nm = AllocVec(sizeof(struct NewMenu) * n, 0)))
  241.     {
  242.         return NULL;
  243.     }
  244.  
  245.     /*
  246.         build the standard menus from the MFWindowNewMenu array
  247.     */
  248.     for (pNewMenu = nm, i = 0; i < n; i++, pNewMenu++)
  249.     {
  250.         *pNewMenu = MFWindowNewMenu[i];
  251.  
  252.         if (pNewMenu->nm_Label != NM_BARLABEL  &&
  253.             pNewMenu->nm_Type  != NM_END)
  254.         {
  255.             pNewMenu->nm_CommKey = GetStr((LONG)pNewMenu->nm_Label);
  256.             pNewMenu->nm_Label = pNewMenu->nm_CommKey+2;
  257.  
  258.             if (pNewMenu->nm_CommKey[0] == ' ')
  259.             {
  260.                 pNewMenu->nm_CommKey = NULL;
  261.             }
  262.         }
  263.     }
  264.  
  265.     return nm;
  266. }
  267.  
  268.  
  269. /*
  270.     function :    frees the memory used for the image file name
  271.  
  272.     parameters :  data = pointer to the MFWindowData
  273. */
  274. void DeleteMineFieldImageFileName(struct MFWindowData * data)
  275. {
  276.     if (data->MineFieldImageFile != NULL)
  277.     {
  278.         FreeVec(data->MineFieldImageFile);
  279.         data->MineFieldImageFile = NULL;
  280.     }
  281. }
  282.  
  283.  
  284. /*
  285.     function :    delete any existing image file name and sets the given
  286.                   new image file name
  287.  
  288.     parameters :  data = pointer to the MFWindowData
  289.                   newname = the new image file name or NULL to clear the
  290.                             existing file name and use the default image
  291.  
  292. */
  293. void SetMineFieldImageFileName(struct MFWindowData * data, STRPTR newname)
  294. {
  295.     DeleteMineFieldImageFileName(data);
  296.  
  297.     if (newname)
  298.     {
  299.         int l = strlen(newname) + 1;
  300.         data->MineFieldImageFile = (STRPTR)AllocVec(l, 0);
  301.         if (data->MineFieldImageFile)
  302.         {
  303.             strcpy(data->MineFieldImageFile, newname);
  304.         }
  305.     }
  306. }
  307.  
  308. /*
  309.     function :    frees the memory used for the image file name
  310.  
  311.     parameters :  data = pointer to the MFWindowData
  312. */
  313. void DeleteStartButtonImageFileName(struct MFWindowData * data)
  314. {
  315.     if (data->StartButtonImageFile != NULL)
  316.     {
  317.         FreeVec(data->StartButtonImageFile);
  318.         data->StartButtonImageFile = NULL;
  319.     }
  320. }
  321.  
  322.  
  323. /*
  324.     function :    delete any existing image file name and sets the given
  325.                   new image file name
  326.  
  327.     parameters :  data = pointer to the MFWindowData
  328.                   newname = the new image file name or NULL to clear the
  329.                             existing file name and use the default image
  330.  
  331. */
  332. void SetStartButtonImageFileName(struct MFWindowData * data, STRPTR newname)
  333. {
  334.     DeleteStartButtonImageFileName(data);
  335.  
  336.     if (newname)
  337.     {
  338.         int l = strlen(newname) + 1;
  339.         data->StartButtonImageFile = (STRPTR)AllocVec(l, 0);
  340.         if (data->StartButtonImageFile)
  341.         {
  342.             strcpy(data->StartButtonImageFile, newname);
  343.         }
  344.     }
  345. }
  346.  
  347. /*
  348.     function :    frees the memory used for the image file name
  349.  
  350.     parameters :  data = pointer to the MFWindowData
  351. */
  352. void DeleteMinesDigitsImageFileName(struct MFWindowData * data)
  353. {
  354.     if (data->MinesDigitsImageFile != NULL)
  355.     {
  356.         FreeVec(data->MinesDigitsImageFile);
  357.         data->MinesDigitsImageFile = NULL;
  358.     }
  359. }
  360.  
  361.  
  362. /*
  363.     function :    delete any existing image file name and sets the given
  364.                   new image file name
  365.  
  366.     parameters :  data = pointer to the MFWindowData
  367.                   newname = the new image file name or NULL to clear the
  368.                             existing file name and use the default image
  369.  
  370. */
  371. void SetMinesDigitsImageFileName(struct MFWindowData * data, STRPTR newname)
  372. {
  373.     DeleteMinesDigitsImageFileName(data);
  374.  
  375.     if (newname)
  376.     {
  377.         int l = strlen(newname) + 1;
  378.         data->MinesDigitsImageFile = (STRPTR)AllocVec(l, 0);
  379.         if (data->MinesDigitsImageFile)
  380.         {
  381.             strcpy(data->MinesDigitsImageFile, newname);
  382.         }
  383.     }
  384. }
  385.  
  386. /*
  387.     function :    frees the memory used for the image file name
  388.  
  389.     parameters :  data = pointer to the MFWindowData
  390. */
  391. void DeleteTimeDigitsImageFileName(struct MFWindowData * data)
  392. {
  393.     if (data->TimeDigitsImageFile != NULL)
  394.     {
  395.         FreeVec(data->TimeDigitsImageFile);
  396.         data->TimeDigitsImageFile = NULL;
  397.     }
  398. }
  399.  
  400.  
  401. /*
  402.     function :    delete any existing image file name and sets the given
  403.                   new image file name
  404.  
  405.     parameters :  data = pointer to the MFWindowData
  406.                   newname = the new image file name or NULL to clear the
  407.                             existing file name and use the default image
  408.  
  409. */
  410. void SetTimeDigitsImageFileName(struct MFWindowData * data, STRPTR newname)
  411. {
  412.     DeleteTimeDigitsImageFileName(data);
  413.  
  414.     if (newname)
  415.     {
  416.         int l = strlen(newname) + 1;
  417.         data->TimeDigitsImageFile = (STRPTR)AllocVec(l, 0);
  418.         if (data->TimeDigitsImageFile)
  419.         {
  420.             strcpy(data->TimeDigitsImageFile, newname);
  421.         }
  422.     }
  423. }
  424.  
  425.  
  426.  
  427. /*
  428.     function :    OM_NEW method handler for MFWindow class
  429. */
  430. static ULONG mNew(struct IClass *cl, Object *obj, struct opSet *msg)
  431. {
  432.     ULONG level;
  433.     BOOL safestart;
  434.     STRPTR minefieldimage, startbuttonimage,
  435.            minesdigitsimage, timedigitsimage;
  436.     struct MFWindowData *data;
  437.     struct LevelDataList levels;
  438.     struct LevelData * pLevel;
  439.     struct NewMenu * nm;
  440.     Object *minesdisp, *timedisp, *facebutt,
  441.            *minefield, *strip, *levelmenu;
  442.  
  443.     /*
  444.         initialize pointers to allocated data
  445.     */
  446.     strip = NULL;
  447.     levelmenu = NULL;
  448.     levels.NumLevels = 0;
  449.     levels.CurrentLevel = 0;
  450.     levels.Flags = 0;
  451.     levels.LevelList = NULL;
  452.  
  453.     /*
  454.         initialize game options for window content creation
  455.     */
  456.     minefieldimage = (STRPTR)GetTagData(MUIA_MFWindow_MineFieldImage,
  457.                                                 NULL, msg->ops_AttrList);
  458.     startbuttonimage = (STRPTR)GetTagData(MUIA_MFWindow_StartButtonImage,
  459.                                                 NULL, msg->ops_AttrList);
  460.     minesdigitsimage = (STRPTR)GetTagData(MUIA_MFWindow_MinesDigitsImage,
  461.                                                 NULL, msg->ops_AttrList);
  462.     timedigitsimage = (STRPTR)GetTagData(MUIA_MFWindow_TimeDigitsImage,
  463.                                                 NULL, msg->ops_AttrList);
  464.     safestart = (BOOL)GetTagData(MUIA_MFWindow_SafeStart, FALSE,
  465.                                                       msg->ops_AttrList);
  466.  
  467.     /*
  468.         load the level data
  469.     */
  470.     LoadLevelData(&levels, NULL);
  471.  
  472.     /*
  473.         create the menustrip for the window, do not fail if we fail to
  474.         create the menustrip as we can live without it
  475.     */
  476.     nm = CreateNewMenus();
  477.     if (nm)
  478.     {
  479.         strip = MUI_MakeObject(MUIO_MenustripNM, nm, 0);
  480.         if (strip)
  481.         {
  482.             Object * safestartitem;
  483.             levelmenu = (APTR)DoMethod(strip, MUIM_FindUData, MENU_LEVEL);
  484.             safestartitem = (APTR)DoMethod(strip, MUIM_FindUData,
  485.                                                   MENU_GAME_SAFESTART);
  486.             if (safestartitem)
  487.             {
  488.                 SetAttrs(safestartitem, MUIA_Menuitem_Checked, safestart,
  489.                                         TAG_DONE);
  490.             }
  491.         }
  492.         else
  493.         {
  494.             FreeVec(nm);
  495.             DisposeLevelData(&levels);
  496.             nm = NULL;
  497.         }
  498.     }
  499.  
  500.     /*
  501.         create the window object
  502.     */
  503.     obj = (Object *)DoSuperNew(cl, obj,
  504.             MUIA_Window_Title, GetStr(MSG_MFWINDOW_TITLE),
  505.             MUIA_Window_ID, MAKE_ID('M','I','N','E'),
  506.             (strip) ? MUIA_Window_Menustrip : TAG_IGNORE, strip,
  507.             WindowContents, VGroup,
  508.                 Child, HGroup,
  509.                     GroupFrame,
  510.                     Child, minesdisp = NewObject(mccDigits->mcc_Class, NULL,
  511.                         TextFrame,
  512.                         MUIA_InputMode, MUIV_InputMode_None,
  513.                         MUIA_ShortHelp, GetStr(MSG_MINESLEFT_HELP),
  514.                         MUIA_Digits_ImageFile, minesdigitsimage,
  515.                         TAG_DONE),
  516.  
  517.                     Child, HSpace(0),
  518.  
  519.                     Child, facebutt = NewObject(mccFaceButton->mcc_Class, NULL,
  520.                         MUIA_InputMode, MUIV_InputMode_RelVerify,
  521.                         MUIA_ShortHelp, GetStr(MSG_STARTBUTT_HELP),
  522.                         MUIA_FaceButton_ImageFile, startbuttonimage,
  523.                         TAG_DONE),
  524.  
  525.                     Child, HSpace(0),
  526.  
  527.                     Child, timedisp = NewObject(mccDigits->mcc_Class, NULL,
  528.                         TextFrame,
  529.                         MUIA_InputMode, MUIV_InputMode_None,
  530.                         MUIA_ShortHelp, GetStr(MSG_TIMETAKEN_HELP),
  531.                         MUIA_Digits_ImageFile, timedigitsimage,
  532.                         TAG_DONE),
  533.                     End,
  534.  
  535.                 Child, minefield = NewObject(mccMineField->mcc_Class,NULL,
  536.                     MUIA_MineField_SafeStart, safestart,
  537.                     MUIA_MineField_ImageFile, minefieldimage,
  538.                     TextFrame,
  539.                     TAG_DONE),
  540.                 End,
  541.  
  542.             TAG_MORE, msg->ops_AttrList);
  543.  
  544.     if (obj)
  545.     {
  546.         /*
  547.             initialize instance data
  548.         */
  549.         data = INST_DATA(cl, obj);
  550.  
  551.         data->NewMenus = nm;
  552.         data->MinesDisp = minesdisp;
  553.         data->TimeDisp = timedisp;
  554.         data->FaceButton = facebutt;
  555.         data->MineField = minefield;
  556.         data->MenuStrip = strip;
  557.         data->LevelMenu = levelmenu;
  558.         data->Levels = levels;
  559.         data->MUIAboutWindow = NULL;
  560.         data->LastBestTimeName[0] = 0;
  561.         data->Options = 0;
  562.         data->MineFieldImageFile = NULL;
  563.         data->StartButtonImageFile = NULL;
  564.         data->MinesDigitsImageFile = NULL;
  565.         data->TimeDigitsImageFile = NULL;
  566.         if (safestart)
  567.         {
  568.             data->Options |= MFW_OPT_SAFESTART;
  569.         }
  570.         SetMineFieldImageFileName(data, minefieldimage);
  571.         SetStartButtonImageFileName(data, startbuttonimage);
  572.         SetMinesDigitsImageFileName(data, minesdigitsimage);
  573.         SetTimeDigitsImageFileName(data, timedigitsimage);
  574.  
  575.         /*
  576.            initialize level to none set
  577.         */
  578.         level = levels.CurrentLevel;
  579.         data->LevelMenuCheck = 0;
  580.         data->Levels.CurrentLevel = 0;
  581.  
  582.         /*
  583.             build the level menu items
  584.         */
  585.         BuildLevelMenu(data);
  586.  
  587.         /*
  588.             set the mine field difficulty level
  589.         */
  590.         pLevel = FindLevel(&data->Levels, level);
  591.         level = (pLevel)
  592.                     ? pLevel->Level
  593.                     : (data->Levels.LevelList)
  594.                         ? data->Levels.LevelList->Level
  595.                         : DEFAULT_LEVEL;
  596.  
  597.         SetLevel(obj, data, level);
  598.  
  599.         /*
  600.             setup notifications between the child objects
  601.         */
  602.         DoMethod(data->FaceButton, MUIM_Notify, MUIA_Pressed, FALSE,
  603.                     data->MineField, 1, MUIM_MineField_Init);
  604.  
  605.         DoMethod(data->MineField, MUIM_Notify, MUIA_MineField_MinesLeft, MUIV_EveryTime,
  606.                     data->MinesDisp, 3, MUIM_Set, MUIA_Digits_Number, MUIV_TriggerValue);
  607.  
  608.         DoMethod(data->MineField, MUIM_Notify, MUIA_MineField_GameWon, TRUE,
  609.                     data->FaceButton, 3, MUIM_Set, MUIA_FaceButton_ImageIdx,
  610.                                                     MUIV_FaceButton_ImageIdx_Good);
  611.  
  612.         DoMethod(data->MineField, MUIM_Notify, MUIA_MineField_GameWon, TRUE,
  613.                     obj, 1, MUIM_MFWindow_CheckBestTime);
  614.  
  615.         DoMethod(data->MineField, MUIM_Notify, MUIA_MineField_GameLost, TRUE,
  616.                     data->FaceButton, 3, MUIM_Set, MUIA_FaceButton_ImageIdx,
  617.                                                     MUIV_FaceButton_ImageIdx_Bad);
  618.  
  619.         DoMethod(data->MineField, MUIM_Notify, MUIA_MineField_GameInitialized, TRUE,
  620.                     data->FaceButton, 3, MUIM_Set, MUIA_FaceButton_ImageIdx,
  621.                                                     MUIV_FaceButton_ImageIdx_Normal);
  622.  
  623.         DoMethod(data->MineField, MUIM_Notify, MUIA_MineField_MouseDown, TRUE,
  624.                     data->FaceButton, 3, MUIM_Set, MUIA_FaceButton_ImageIdx,
  625.                                                     MUIV_FaceButton_ImageIdx_Oh);
  626.  
  627.         DoMethod(data->MineField, MUIM_Notify, MUIA_MineField_MouseDown, FALSE,
  628.                     data->FaceButton, 3, MUIM_Set, MUIA_FaceButton_ImageIdx,
  629.                                                     MUIV_FaceButton_ImageIdx_Normal);
  630.  
  631.         DoMethod(data->MineField, MUIM_Notify, MUIA_MineField_TimeTaken, MUIV_EveryTime,
  632.                     data->TimeDisp, 3, MUIM_Set, MUIA_Digits_Number, MUIV_TriggerValue);
  633.  
  634.     }
  635.     else
  636.     {
  637.         /*
  638.             super class could not be created, delete the new menu
  639.             array if it was allocated and dispose of the level data
  640.         */
  641.         if (nm)
  642.         {
  643.             FreeVec((APTR)nm);
  644.         }
  645.         DisposeLevelData(&levels);
  646.     }
  647.  
  648.     return (ULONG)obj;
  649. }
  650.  
  651.  
  652. /*
  653.     function :    OM_DELETE method handler for MFWindow class
  654. */
  655. static ULONG mDispose(struct IClass *cl, Object *obj, Msg msg)
  656. {
  657.     struct MFWindowData *data = INST_DATA(cl, obj);
  658.  
  659.     if (data->NewMenus)
  660.     {
  661.         FreeVec((APTR)data->NewMenus);
  662.     }
  663.     SaveLevelData(&data->Levels, NULL);
  664.     DisposeLevelData(&data->Levels);
  665.  
  666.     DeleteMineFieldImageFileName(data);
  667.     DeleteStartButtonImageFileName(data);
  668.     DeleteMinesDigitsImageFileName(data);
  669.     DeleteTimeDigitsImageFileName(data);
  670.  
  671.     return DoSuperMethodA(cl, obj, msg);
  672. }
  673.  
  674.  
  675. /*
  676.     function :    OM_SET method handler for MFWindow class
  677. */
  678. static ULONG mSet(struct IClass *cl, Object *obj, struct opSet * msg)
  679. {
  680.     struct MFWindowData *data = INST_DATA(cl,obj);
  681.     struct TagItem *tags, *tag;
  682.     ULONG WinOpen = FALSE;
  683.     ULONG ret;
  684.  
  685.     for (tags = msg->ops_AttrList; tag = NextTagItem(&tags); )
  686.     {
  687.         switch (tag->ti_Tag)
  688.         {
  689.             case MUIA_MFWindow_Level:
  690.             {
  691.                 SetLevel(obj, data, tag->ti_Data);
  692.                 break;
  693.             }
  694.  
  695.             case MUIA_Window_Open:
  696.             {
  697.                 WinOpen = tag->ti_Data;
  698.                 break;
  699.             }
  700.  
  701.             case MUIA_Window_MenuAction:
  702.             {
  703.                 switch (tag->ti_Data)
  704.                 {
  705.                     case MENU_GAME_START:
  706.                     {
  707.                         DoMethod(data->MineField, MUIM_MineField_Init);
  708.                         break;
  709.                     }
  710.  
  711.                     case MENU_GAME_BESTTIMES:
  712.                     {
  713.                         ShowBestTimes(obj, &data->Levels, -1);
  714.                         break;
  715.                     }
  716.  
  717.                     case MENU_GAME_LEVELS:
  718.                     {
  719.                         SetupLevels(obj, data);
  720.                         break;
  721.                     }
  722.  
  723.                     case MENU_GAME_IMAGES:
  724.                     {
  725.                         SetupImages(obj, data);
  726.                         break;
  727.                     }
  728.  
  729.                     case MENU_GAME_SAFESTART:
  730.                     {
  731.                         if (data->MenuStrip)
  732.                         {
  733.                             Object * ssitem = (APTR)DoMethod(data->MenuStrip,
  734.                                                              MUIM_FindUData,
  735.                                                              MENU_GAME_SAFESTART);
  736.                             if (ssitem)
  737.                             {
  738.                                 ULONG l;
  739.                                 if (GetAttr(MUIA_Menuitem_Checked, ssitem, &l))
  740.                                 {
  741.                                     if (l)
  742.                                     {
  743.                                         data->Options |= MFW_OPT_SAFESTART;
  744.                                     }
  745.                                     else
  746.                                     {
  747.                                         data->Options &= ~MFW_OPT_SAFESTART;
  748.                                     }
  749.                                     SetAttrs(data->MineField,
  750.                                                 MUIA_MineField_SafeStart, l,
  751.                                                 TAG_DONE);
  752.                                 }
  753.                             }
  754.                         }
  755.                         break;
  756.                     }
  757.  
  758.                     case MENU_GAME_INFO:
  759.                     {
  760.                         ShowProgInfo(obj);
  761.                         break;
  762.                     }
  763.  
  764.                     case MENU_GAME_QUIT:
  765.                     {
  766.                         SetAttrs(obj, MUIA_Window_CloseRequest, TRUE, TAG_DONE);
  767.                         break;
  768.                     }
  769.  
  770.                     case MENU_MUI_ABOUT:
  771.                     {
  772.                         if (!data->MUIAboutWindow)
  773.                         {
  774.                             data->MUIAboutWindow = AboutmuiObject,
  775.                                 MUIA_Window_RefWindow, obj,
  776.                                 MUIA_Aboutmui_Application, _app(obj),
  777.                                 End;
  778.                         }
  779.  
  780.                         if (data->MUIAboutWindow)
  781.                         {
  782.                             SetAttrs(data->MUIAboutWindow, MUIA_Window_Open, TRUE,
  783.                                                            TAG_DONE);
  784.                         }
  785.                         break;
  786.                     }
  787.  
  788.                     case MENU_MUI_SETTINGS:
  789.                     {
  790.                         DoMethod(_app(obj), MUIM_Application_OpenConfigWindow, 0);
  791.                         break;
  792.                     }
  793.  
  794.                     default:
  795.                     {
  796.                         struct LevelData * pLevel = FindMenuId(&data->Levels,
  797.                                                                 tag->ti_Data);
  798.                         if (pLevel)
  799.                         {
  800.                             SetLevel(obj, data, pLevel->Level);
  801.                         }
  802.                         break;
  803.                     }
  804.                 }
  805.             }
  806.         }
  807.     }
  808.  
  809.     ret = DoSuperMethodA(cl, obj, (APTR)msg);
  810.  
  811.     /*
  812.         if the window was opened then check that it did actually open
  813.         and if it did not then display an error requester, set the
  814.         current level to the default level (because the window may have
  815.         failed to open because the mine field was too large for the
  816.         screen) and exit the application
  817.     */
  818.     if (WinOpen)
  819.     {
  820.         DoMethod(obj, OM_GET, MUIA_Window_Open, &WinOpen);
  821.         if (!WinOpen)
  822.         {
  823.             MUI_RequestA(_app(obj), NULL, 0, GetStr(MSG_MFWINDOW_TITLE),
  824.                                              GetStr(MSG_EXIT_GADGET),
  825.                                              GetStr(MSG_MFWINDOW_OPEN_ERR),
  826.                                              NULL);
  827.             data->Levels.CurrentLevel = DEFAULT_LEVEL;
  828.             DoMethod(_app(obj), MUIM_Application_ReturnID,
  829.                                 MUIV_Application_ReturnID_Quit);
  830.         }
  831.     }
  832.  
  833.     return ret;
  834. }
  835.  
  836. /*
  837.     function :    OM_GET method handler for MFWindow class
  838. */
  839. static ULONG mGet(struct IClass *cl, Object *obj, struct opGet * msg)
  840. {
  841.     struct MFWindowData *data = INST_DATA(cl, obj);
  842.     ULONG *store = msg->opg_Storage;
  843.  
  844.     switch (msg->opg_AttrID)
  845.     {
  846.         case MUIA_MFWindow_Level:
  847.             *store = (ULONG)data->Levels.CurrentLevel;
  848.             return TRUE;
  849.  
  850.         case MUIA_MFWindow_MineFieldImage:
  851.             *store = (ULONG)data->MineFieldImageFile;
  852.             return TRUE;
  853.  
  854.         case MUIA_MFWindow_StartButtonImage:
  855.             *store = (ULONG)data->StartButtonImageFile;
  856.             return TRUE;
  857.  
  858.         case MUIA_MFWindow_MinesDigitsImage:
  859.             *store = (ULONG)data->MinesDigitsImageFile;
  860.             return TRUE;
  861.  
  862.         case MUIA_MFWindow_TimeDigitsImage:
  863.             *store = (ULONG)data->TimeDigitsImageFile;
  864.             return TRUE;
  865.  
  866.         case MUIA_MFWindow_SafeStart:
  867.             *store = (ULONG)((data->Options & MFW_OPT_SAFESTART) != 0);
  868.             return TRUE;
  869.     }
  870.  
  871.     return DoSuperMethodA(cl, obj, (APTR)msg);
  872. }
  873.  
  874. /*
  875.     function :    MUIM_MFWindow_CheckBestTime method handler for MFWindow class
  876. */
  877. static ULONG mCheckBestTime(struct IClass *cl, Object *obj, Msg msg)
  878. {
  879.     struct MFWindowData * data = INST_DATA(cl, obj);
  880.     CheckBestTime(obj, data);
  881.     return 0;
  882. }
  883.  
  884. /*
  885.     function :    class dispatcher
  886. */
  887. SAVEDS ASM ULONG MFWindowDispatcher(
  888.         REG(a0) struct IClass *cl,
  889.         REG(a2) Object *obj,
  890.         REG(a1) Msg msg)
  891. {
  892.     switch (msg->MethodID)
  893.     {
  894.         case OM_NEW:     return mNew    (cl, obj, (APTR)msg);
  895.         case OM_DISPOSE: return mDispose(cl, obj, (APTR)msg);
  896.         case OM_SET:     return mSet    (cl, obj, (APTR)msg);
  897.         case OM_GET:     return mGet    (cl, obj, (APTR)msg);
  898.  
  899.         case MUIM_MFWindow_CheckBestTime:
  900.             return mCheckBestTime(cl, obj, (APTR)msg);
  901.     }
  902.  
  903.     return DoSuperMethodA(cl, obj, msg);
  904. }
  905.  
  906.  
  907. /*
  908.     function :    sets the difficulty level
  909.  
  910.     parameters :  obj = pointer to the MFWindow object
  911.                   data = pointer to the MFWindow data
  912.                   level = new difficulty level to set
  913. */
  914. static void SetLevel(Object * obj, struct MFWindowData * data, ULONG level)
  915. {
  916.     static char WinTitle[64];
  917.  
  918.     /*
  919.         check for non-NULL level and if the level has actually changed
  920.     */
  921.     if (level  &&  level != data->Levels.CurrentLevel)
  922.     {
  923.         struct LevelData * pLevel;
  924.         ULONG opened = 0, menuid = 0;
  925.  
  926.         /*
  927.             set the new level in the window data
  928.         */
  929.         data->Levels.CurrentLevel = level;
  930.  
  931.         /*
  932.             detemine if this is a defined level and if it is then
  933.             get the menu item for this level
  934.         */
  935.         pLevel = FindLevel(&data->Levels, level);
  936.         if (pLevel)
  937.         {
  938.             menuid = pLevel->MenuId;
  939.             sprintf(WinTitle, GetStr(MSG_MFWINDOW_TITLE_FMT), pLevel->Name);
  940.         }
  941.         else
  942.         {
  943.             strcpy(WinTitle, GetStr(MSG_MFWINDOW_TITLE));
  944.         }
  945.  
  946.         /*
  947.             check if the window is opened and if so close it
  948.             to make the changes to mine field
  949.         */
  950.         DoMethod(obj, OM_GET, MUIA_Window_Open, &opened);
  951.         if (opened)
  952.         {
  953.             SetAttrs(obj, MUIA_Window_Open, FALSE, TAG_DONE);
  954.         }
  955.  
  956.         /*
  957.             make the changes to the mine field
  958.         */
  959.         SetAttrs(data->MineField, MUIA_MineField_Width, LVL_WIDTH(level),
  960.                                   MUIA_MineField_Height, LVL_HEIGHT(level),
  961.                                   MUIA_MineField_NumMines, LVL_MINES(level),
  962.                                   TAG_DONE);
  963.  
  964.         /*
  965.             set window title for this level
  966.         */
  967.         SetAttrs(obj, MUIA_Window_Title, WinTitle, TAG_DONE);
  968.  
  969.         /*
  970.             reopen the window if it was previously open
  971.         */
  972.         if (opened)
  973.         {
  974.             SetAttrs(obj, MUIA_Window_Open, TRUE, TAG_DONE);
  975.         }
  976.  
  977.         /*
  978.             if there is a menu item for the level then check it
  979.             otherwise uncheck any checked level menu item
  980.         */
  981.         if (menuid)
  982.         {
  983.             DoMethod(obj, MUIM_Window_SetMenuCheck, menuid, TRUE);
  984.             data->LevelMenuCheck = menuid;
  985.         }
  986.         else if (data->LevelMenuCheck)
  987.         {
  988.             DoMethod(obj, MUIM_Window_SetMenuCheck, data->LevelMenuCheck, FALSE);
  989.             data->LevelMenuCheck = 0;
  990.         }
  991.     }
  992. }
  993.  
  994. /*
  995.     function :    checks the last game time for a best time for the
  996.                   current difficulty level
  997.  
  998.     parameters :  obj = pointer to the MFWindow object
  999.                   data = pointer to obj's MFWindowData
  1000.  
  1001.     return :      none
  1002. */
  1003. static void CheckBestTime(Object * obj, struct MFWindowData * data)
  1004. {
  1005.     /*
  1006.         first check if the current level is a named level
  1007.     */
  1008.     struct LevelData * pLevel = FindCurrentLevel(&data->Levels);
  1009.     if (pLevel)
  1010.     {
  1011.         /*
  1012.             get the time taken from the minefield and make sure it is
  1013.             valid i.e. greater than zero
  1014.         */
  1015.         LONG lastTime = -1;
  1016.         DoMethod(data->MineField, OM_GET, MUIA_MineField_TimeTaken, &lastTime);
  1017.         if (lastTime > 0)
  1018.         {
  1019.             int i;
  1020.             struct BestTime * p;
  1021.             /*
  1022.                 check if the last game's time is less than any of the
  1023.                 three best times for the level
  1024.             */
  1025.             for (i = 0, p = pLevel->BestTimes; i < 3; i++, p++)
  1026.             {
  1027.                 if (p->Time <= 0  ||  lastTime < p->Time)
  1028.                 {
  1029.                     break;
  1030.                 }
  1031.             }
  1032.             if (i < 3)
  1033.             {
  1034.                 /*
  1035.                     we have a new best time, move the best time being
  1036.                     displaced and all later best times down one in the
  1037.                     list, instert the new best time and get the name of
  1038.                     the player
  1039.                 */
  1040.                 int j;
  1041.                 for (j = 2; j > i; j--)
  1042.                 {
  1043.                     pLevel->BestTimes[j] = pLevel->BestTimes[j - 1];
  1044.                 }
  1045.                 p->Time = lastTime;
  1046.                 if (data->LastBestTimeName[0])
  1047.                 {
  1048.                     strcpy(p->Name, data->LastBestTimeName);
  1049.                 }
  1050.                 GetBestTimeName(obj, pLevel, i);
  1051.                 if (p->Name[0])
  1052.                 {
  1053.                     strcpy(data->LastBestTimeName, p->Name);
  1054.                 }
  1055.                 /*
  1056.                     show the new best times
  1057.                 */
  1058.                 ShowBestTimes(obj, &data->Levels, i);
  1059.             } // new best time
  1060.         } // (lastTime > 0)
  1061.     } // (pLevel)
  1062. }
  1063.  
  1064.  
  1065.  
  1066.  
  1067. #define BTNW_Done   101
  1068.  
  1069. static BOOL GetBestTimeName(Object * obj, struct LevelData * pLevel, int rank)
  1070. {
  1071.     BOOL ret = FALSE;
  1072.     Object *win, *namestr, *okbutt;
  1073.     static char msgbuff[256];
  1074.     static LONG rankid[3] = {MSG_BESTTIME_RANK_1,
  1075.                              MSG_BESTTIME_RANK_2,
  1076.                              MSG_BESTTIME_RANK_3};
  1077.  
  1078.     /*
  1079.         format the message with the level's name
  1080.     */
  1081.     sprintf(msgbuff, GetStr(MSG_BESTTIME_FMT), GetStr(rankid[rank]), pLevel->Name);
  1082.  
  1083.     /*
  1084.         create the best time name window
  1085.     */
  1086.     win = WindowObject,
  1087.         MUIA_Window_Title, GetStr(MSG_BESTTIME_NAME_TITLE),
  1088.         MUIA_Window_RefWindow, obj,
  1089.         MUIA_Window_LeftEdge, MUIV_Window_LeftEdge_Centered,
  1090.         MUIA_Window_TopEdge, MUIV_Window_TopEdge_Centered,
  1091.         WindowContents, VGroup,
  1092.             Child, TextObject,
  1093.                 TextFrame,
  1094.                 MUIA_Background, MUII_TextBack,
  1095.                 MUIA_Text_SetMax, TRUE,
  1096.                 MUIA_Text_SetMin, TRUE,
  1097.                 MUIA_Text_Contents, msgbuff,
  1098.                 End,
  1099.  
  1100.             Child, namestr = StringObject,
  1101.                 StringFrame,
  1102.                 MUIA_CycleChain, 1,
  1103.                 MUIA_String_MaxLen, BT_NAME_SIZE,
  1104.                 MUIA_String_Contents, pLevel->BestTimes[rank].Name,
  1105.                 End,
  1106.  
  1107.             Child, okbutt = TextObject,
  1108.                 ButtonFrame,
  1109.                 MUIA_Background, MUII_ButtonBack,
  1110.                 MUIA_Text_PreParse, "\033c",
  1111.                 MUIA_Text_Contents, GetStr(MSG_OKBUTT_LABEL) + 2,
  1112.                 MUIA_ControlChar, '\r',
  1113.                 MUIA_InputMode, MUIV_InputMode_RelVerify,
  1114.                 End,
  1115.  
  1116.             End,
  1117.         End;
  1118.  
  1119.     /*
  1120.         check if window was successfully created
  1121.     */
  1122.     if (win)
  1123.     {
  1124.         ULONG sigs = 0;
  1125.         BOOL running = TRUE;
  1126.         Object * app = _app(obj);
  1127.  
  1128.         /*
  1129.             put parent window to sleep
  1130.         */
  1131.         SetAttrs(obj, MUIA_Window_Sleep, TRUE, TAG_DONE);
  1132.         /*
  1133.             add the best time name window to the application
  1134.         */
  1135.         DoMethod(app, OM_ADDMEMBER, win);
  1136.         /*
  1137.             setup notifications
  1138.         */
  1139.         DoMethod(win, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
  1140.                     app, 2, MUIM_Application_ReturnID, BTNW_Done);
  1141.  
  1142.         DoMethod(okbutt, MUIM_Notify, MUIA_Pressed, FALSE,
  1143.                     app, 2, MUIM_Application_ReturnID, BTNW_Done);
  1144.  
  1145.         DoMethod(namestr, MUIM_Notify, MUIA_String_Acknowledge, MUIV_TriggerValue,
  1146.                     app, 2, MUIM_Application_ReturnID, BTNW_Done);
  1147.  
  1148.         /*
  1149.             open the best time name window
  1150.         */
  1151.         SetAttrs(win, MUIA_Window_Open, TRUE,
  1152.                       MUIA_Window_DefaultObject, okbutt,
  1153.                       MUIA_Window_ActiveObject, namestr,
  1154.                       TAG_DONE);
  1155.  
  1156.         /*
  1157.             enter the input loop
  1158.         */
  1159.         while (running)
  1160.         {
  1161.             switch (DoMethod(app, MUIM_Application_NewInput, &sigs))
  1162.             {
  1163.                 case MUIV_Application_ReturnID_Quit:
  1164.                     /*
  1165.                         re-send the quit id so the main app loop can exit
  1166.                     */
  1167.                     DoMethod(app, MUIM_Application_ReturnID,
  1168.                                   MUIV_Application_ReturnID_Quit);
  1169.                     running = FALSE;
  1170.                     break;
  1171.  
  1172.                 case BTNW_Done:
  1173.                     /*
  1174.                         user done with best time name window
  1175.                     */
  1176.                     ret = TRUE;
  1177.                     running = FALSE;
  1178.                     break;
  1179.  
  1180.                 default:
  1181.                     if (sigs)
  1182.                     {
  1183.                         sigs = Wait(sigs | SIGBREAKF_CTRL_C);
  1184.                         if (sigs & SIGBREAKF_CTRL_C)
  1185.                         {
  1186.                             DoMethod(app, MUIM_Application_ReturnID,
  1187.                                           MUIV_Application_ReturnID_Quit);
  1188.                             running = FALSE;
  1189.                         }
  1190.                     }
  1191.                 break;
  1192.             }
  1193.         }
  1194.  
  1195.         /*
  1196.             close the window
  1197.         */
  1198.         SetAttrs(win, MUIA_Window_Open, FALSE, TAG_DONE);
  1199.  
  1200.         /*
  1201.             check if we left the input loop because the window was closed
  1202.             or because the application is terminating
  1203.         */
  1204.         if (ret)
  1205.         {
  1206.             /*
  1207.                 the window closed normally so get the name from the
  1208.                 window's name string and copy it to the LevelData
  1209.                 and to the last best time name
  1210.             */
  1211.             STRPTR pName = NULL;
  1212.  
  1213.             DoMethod(namestr, OM_GET, MUIA_String_Contents, &pName);
  1214.             if (pName)
  1215.             {
  1216.                 strcpy(pLevel->BestTimes[rank].Name, pName);
  1217.             }
  1218.         }
  1219.  
  1220.         /*
  1221.             detach the window from the app and dispose of it
  1222.         */
  1223.         DoMethod(app, OM_REMMEMBER, win);
  1224.         MUI_DisposeObject(win);
  1225.  
  1226.         /*
  1227.             wake up the parent window
  1228.         */
  1229.         SetAttrs(obj, MUIA_Window_Sleep, FALSE, TAG_DONE);
  1230.     }
  1231.  
  1232.     return ret;
  1233. }
  1234.  
  1235.  
  1236. /*
  1237.     function :      shows the best times window
  1238.  
  1239.     parameters :    obj = pointer to the parent window object
  1240.                     lList = level data list with the best time data
  1241.                     hiRank = ranking of current level to highlight or -1
  1242. */
  1243.  
  1244. #define BTW_Done    101
  1245.  
  1246. static void ShowBestTimes(Object * obj, struct LevelDataList * lList, int hiRank)
  1247. {
  1248.     Object *win;
  1249.  
  1250.     /*
  1251.         create the best time name window
  1252.     */
  1253.     win =  NewObject(mccBTWindow->mcc_Class,NULL,
  1254.         MUIA_Window_RefWindow, obj,
  1255.         MUIA_Window_LeftEdge, MUIV_Window_LeftEdge_Centered,
  1256.         MUIA_Window_TopEdge, MUIV_Window_TopEdge_Centered,
  1257.         MUIA_BTWindow_LevelList, lList,
  1258.         MUIA_BTWindow_HighlightRank, hiRank,
  1259.         End;
  1260.  
  1261.     /*
  1262.         check if window was successfully created
  1263.     */
  1264.     if (win)
  1265.     {
  1266.         ULONG sigs = 0;
  1267.         BOOL running = TRUE;
  1268.         Object * app = _app(obj);
  1269.  
  1270.         /*
  1271.             put parent window to sleep
  1272.         */
  1273.         SetAttrs(obj, MUIA_Window_Sleep, TRUE, TAG_DONE);
  1274.         /*
  1275.             add the best time window to the application
  1276.         */
  1277.         DoMethod(app, OM_ADDMEMBER, win);
  1278.         /*
  1279.             setup notifications
  1280.         */
  1281.         DoMethod(win, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
  1282.                     app, 2, MUIM_Application_ReturnID, BTW_Done);
  1283.  
  1284.         /*
  1285.             open the best time window
  1286.         */
  1287.         SetAttrs(win, MUIA_Window_Open, TRUE, TAG_DONE);
  1288.  
  1289.         /*
  1290.             enter the input loop
  1291.         */
  1292.         while (running)
  1293.         {
  1294.             switch (DoMethod(app, MUIM_Application_NewInput, &sigs))
  1295.             {
  1296.                 case MUIV_Application_ReturnID_Quit:
  1297.                     /*
  1298.                         re-send the quit id so the main app loop can exit
  1299.                     */
  1300.                     DoMethod(app, MUIM_Application_ReturnID,
  1301.                                   MUIV_Application_ReturnID_Quit);
  1302.                     running = FALSE;
  1303.                     break;
  1304.  
  1305.                 case BTW_Done:
  1306.                     /*
  1307.                         user done with best time window
  1308.                     */
  1309.                     running = FALSE;
  1310.                     break;
  1311.  
  1312.                 default:
  1313.                     if (sigs)
  1314.                     {
  1315.                         sigs = Wait(sigs | SIGBREAKF_CTRL_C);
  1316.                         if (sigs & SIGBREAKF_CTRL_C)
  1317.                         {
  1318.                             DoMethod(app, MUIM_Application_ReturnID,
  1319.                                           MUIV_Application_ReturnID_Quit);
  1320.                             running = FALSE;
  1321.                         }
  1322.                     }
  1323.                     break;
  1324.             }
  1325.         }
  1326.  
  1327.         /*
  1328.             close the window
  1329.         */
  1330.         SetAttrs(win, MUIA_Window_Open, FALSE, TAG_DONE);
  1331.  
  1332.         /*
  1333.             detach the window from the app and dispose of it
  1334.         */
  1335.         DoMethod(app, OM_REMMEMBER, win);
  1336.         MUI_DisposeObject(win);
  1337.  
  1338.         /*
  1339.             wake up the parent window
  1340.         */
  1341.         SetAttrs(obj, MUIA_Window_Sleep, FALSE, TAG_DONE);
  1342.     }
  1343. }
  1344.  
  1345.  
  1346. /*
  1347.     function :    create and show a level edit window for this window's
  1348.                   level data, if the level data is changed then clear
  1349.                   the level menu, delete the old level data, set and save
  1350.                   the new level data for the window and rebuild the level
  1351.                   menu
  1352.  
  1353.     parameters :  obj = the mine field window whose level data is to be edited
  1354.                   data = instance data for the mine field window
  1355.  
  1356.     return :      none
  1357. */
  1358. #define LEW_DONE    101
  1359.  
  1360. static void SetupLevels(Object * obj, struct MFWindowData * data)
  1361. {
  1362.     Object *win;
  1363.     struct LevelDataList rList;
  1364.  
  1365.     /*
  1366.         initialize the return level data list
  1367.     */
  1368.     rList.NumLevels = 0;
  1369.     rList.Flags = 0;
  1370.     rList.LevelList = NULL;
  1371.  
  1372.     /*
  1373.         create the level editor window
  1374.     */
  1375.     win =  NewObject(mccLEWindow->mcc_Class,NULL,
  1376.                         MUIA_Window_RefWindow, obj,
  1377.                         MUIA_Window_LeftEdge, MUIV_Window_LeftEdge_Centered,
  1378.                         MUIA_Window_TopEdge, MUIV_Window_TopEdge_Centered,
  1379.                         MUIA_LEWindow_GivenLevels, &data->Levels,
  1380.                         MUIA_LEWindow_ReturnLevels, &rList,
  1381.                         TAG_DONE);
  1382.  
  1383.     /*
  1384.         check if window was successfully created
  1385.     */
  1386.     if (win)
  1387.     {
  1388.         ULONG sigs = 0;
  1389.         BOOL running = TRUE;
  1390.         Object * app = _app(obj);
  1391.  
  1392.         /*
  1393.             put parent window to sleep
  1394.         */
  1395.         SetAttrs(obj, MUIA_Window_Sleep, TRUE, TAG_DONE);
  1396.         /*
  1397.             add the best time window to the application
  1398.         */
  1399.         DoMethod(app, OM_ADDMEMBER, win);
  1400.         /*
  1401.             setup notifications
  1402.         */
  1403.         DoMethod(win, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
  1404.                     app, 2, MUIM_Application_ReturnID, LEW_DONE);
  1405.  
  1406.         /*
  1407.             open the best time window
  1408.         */
  1409.         SetAttrs(win, MUIA_Window_Open, TRUE, TAG_DONE);
  1410.  
  1411.         /*
  1412.             enter the input loop
  1413.         */
  1414.         while (running)
  1415.         {
  1416.             switch (DoMethod(app, MUIM_Application_NewInput, &sigs))
  1417.             {
  1418.                 case MUIV_Application_ReturnID_Quit:
  1419.                     /*
  1420.                         re-send the quit id so the main app loop can exit
  1421.                     */
  1422.                     DoMethod(app, MUIM_Application_ReturnID,
  1423.                                   MUIV_Application_ReturnID_Quit);
  1424.                     running = FALSE;
  1425.                     break;
  1426.  
  1427.                 case LEW_DONE:
  1428.                     /*
  1429.                         user done with best time window
  1430.                     */
  1431.                     running = FALSE;
  1432.                     break;
  1433.  
  1434.                 default:
  1435.                     if (sigs)
  1436.                     {
  1437.                         sigs = Wait(sigs | SIGBREAKF_CTRL_C);
  1438.                         if (sigs & SIGBREAKF_CTRL_C)
  1439.                         {
  1440.                             DoMethod(app, MUIM_Application_ReturnID,
  1441.                                           MUIV_Application_ReturnID_Quit);
  1442.                             running = FALSE;
  1443.                         }
  1444.                     }
  1445.                     break;
  1446.             }
  1447.         }
  1448.  
  1449.         /*
  1450.             close the window
  1451.         */
  1452.         SetAttrs(win, MUIA_Window_Open, FALSE, TAG_DONE);
  1453.  
  1454.         /*
  1455.             detach the window from the app and dispose of it
  1456.         */
  1457.         DoMethod(app, OM_REMMEMBER, win);
  1458.         MUI_DisposeObject(win);
  1459.  
  1460.         /*
  1461.             check the return level data list to see if level data was updated
  1462.         */
  1463.         if (rList.NumLevels)
  1464.         {
  1465.             /*
  1466.                 the level data has changed, clear the old level menu, dispose
  1467.                 of the existing level data, set and save the new level data,
  1468.                 rebuild the level menu and restart the game with the previous
  1469.                 difficulty level
  1470.             */
  1471.             ULONG CurrentLevel = data->Levels.CurrentLevel;
  1472.             rList.CurrentLevel = CurrentLevel;
  1473.             ClearLevelMenu(data);
  1474.             DisposeLevelData(&data->Levels);
  1475.             data->Levels = rList;
  1476.             SaveLevelData(&rList, NULL);
  1477.             BuildLevelMenu(data);
  1478.             data->Levels.CurrentLevel = 0;
  1479.             SetLevel(obj, data, CurrentLevel);
  1480.         }
  1481.  
  1482.         /*
  1483.             wake up the parent window
  1484.         */
  1485.         SetAttrs(obj, MUIA_Window_Sleep, FALSE, TAG_DONE);
  1486.     }
  1487. }
  1488.  
  1489. /*
  1490.     function :    create and show an image select  window for this window's
  1491.                   object rendering, if the image data has changed then
  1492.                   close the window, update the object's image file attributes
  1493.                   then re-open the window
  1494.  
  1495.     parameters :  obj = the mine field window whose imagery is to be selected
  1496.                   data = instance data for the mine field window
  1497.  
  1498.     return :      none
  1499. */
  1500. #define ISW_CANCEL  101
  1501. #define ISW_OK      102
  1502.  
  1503. static void SetupImages(Object * obj, struct MFWindowData * data)
  1504. {
  1505.     Object *win;
  1506.     struct LevelDataList rList;
  1507.  
  1508.     /*
  1509.         initialize the return level data list
  1510.     */
  1511.     rList.NumLevels = 0;
  1512.     rList.Flags = 0;
  1513.     rList.LevelList = NULL;
  1514.  
  1515.     /*
  1516.         create the level editor window
  1517.     */
  1518.     win =  NewObject(mccISWindow->mcc_Class,NULL,
  1519.                     MUIA_Window_RefWindow, obj,
  1520.                     MUIA_Window_LeftEdge, MUIV_Window_LeftEdge_Centered,
  1521.                     MUIA_Window_TopEdge, MUIV_Window_TopEdge_Centered,
  1522.                     MUIA_ISWindow_MineFieldImage, data->MineFieldImageFile,
  1523.                     MUIA_ISWindow_StartButtonImage, data->StartButtonImageFile,
  1524.                     MUIA_ISWindow_MinesDigitsImage, data->MinesDigitsImageFile,
  1525.                     MUIA_ISWindow_TimeDigitsImage, data->TimeDigitsImageFile,
  1526.                     TAG_DONE);
  1527.  
  1528.     /*
  1529.         check if window was successfully created
  1530.     */
  1531.     if (win)
  1532.     {
  1533.         ULONG exitcode = ISW_CANCEL, sigs = 0;
  1534.         BOOL running = TRUE;
  1535.         Object * app = _app(obj);
  1536.         BPTR lock = CurrentDir(GetProgramDir());
  1537.  
  1538.         /*
  1539.             put parent window to sleep
  1540.         */
  1541.         SetAttrs(obj, MUIA_Window_Sleep, TRUE, TAG_DONE);
  1542.         /*
  1543.             add the best time window to the application
  1544.         */
  1545.         DoMethod(app, OM_ADDMEMBER, win);
  1546.         /*
  1547.             setup notifications
  1548.         */
  1549.         DoMethod(win, MUIM_Notify, MUIA_ISWindow_ExitCode, MUIV_ISWindow_ExitCode_OK,
  1550.                     app, 2, MUIM_Application_ReturnID, ISW_OK);
  1551.         DoMethod(win, MUIM_Notify, MUIA_ISWindow_ExitCode, MUIV_ISWindow_ExitCode_Cancel,
  1552.                     app, 2, MUIM_Application_ReturnID, ISW_CANCEL);
  1553.  
  1554.         /*
  1555.             open the best time window
  1556.         */
  1557.         SetAttrs(win, MUIA_Window_Open, TRUE, TAG_DONE);
  1558.  
  1559.         /*
  1560.             enter the input loop
  1561.         */
  1562.         while (running)
  1563.         {
  1564.             switch (DoMethod(app, MUIM_Application_NewInput, &sigs))
  1565.             {
  1566.                 case MUIV_Application_ReturnID_Quit:
  1567.                     /*
  1568.                         re-send the quit id so the main app loop can exit
  1569.                     */
  1570.                     DoMethod(app, MUIM_Application_ReturnID,
  1571.                                   MUIV_Application_ReturnID_Quit);
  1572.                     running = FALSE;
  1573.                     break;
  1574.  
  1575.                 case ISW_OK:
  1576.                     /*
  1577.                         user exited window with the ok button
  1578.                     */
  1579.                     running = FALSE;
  1580.                     exitcode = ISW_OK;
  1581.                     break;
  1582.  
  1583.                 case ISW_CANCEL:
  1584.                     /*
  1585.                         user exited window with the cancel button
  1586.                     */
  1587.                     running = FALSE;
  1588.                     exitcode = ISW_CANCEL;
  1589.                     break;
  1590.  
  1591.                 default:
  1592.                     if (sigs)
  1593.                     {
  1594.                         sigs = Wait(sigs | SIGBREAKF_CTRL_C);
  1595.                         if (sigs & SIGBREAKF_CTRL_C)
  1596.                         {
  1597.                             DoMethod(app, MUIM_Application_ReturnID,
  1598.                                           MUIV_Application_ReturnID_Quit);
  1599.                             running = FALSE;
  1600.                         }
  1601.                     }
  1602.                     break;
  1603.             }
  1604.         }
  1605.  
  1606.         /*
  1607.             close the window
  1608.         */
  1609.         SetAttrs(win, MUIA_Window_Open, FALSE, TAG_DONE);
  1610.  
  1611.         /*
  1612.             get the exit code, if OK then check for updated data
  1613.         */
  1614.         running = FALSE;    // reuse running flag for update flag
  1615.         if (exitcode == ISW_OK)
  1616.         {
  1617.             STRPTR pstr;
  1618.             int l;
  1619.  
  1620.             /*
  1621.                 get mine field image file and check if updated
  1622.             */
  1623.             if (GetAttr(MUIA_ISWindow_MineFieldImage, win, (ULONG *)&pstr))
  1624.             {
  1625.                 l = (pstr) ? strlen(pstr) : 0;
  1626.                 if (data->MineFieldImageFile == NULL  &&  l != 0  ||
  1627.                     data->MineFieldImageFile != NULL  &&
  1628.                         (l == 0  || strcmpi(pstr, data->MineFieldImageFile) != 0))
  1629.                 {
  1630.                     SetMineFieldImageFileName(data, (l) ? pstr : NULL);
  1631.                     running = TRUE;
  1632.                 }
  1633.             }
  1634.  
  1635.             /*
  1636.                 get start button image file and check if updated
  1637.             */
  1638.             if (GetAttr(MUIA_ISWindow_StartButtonImage, win, (ULONG *)&pstr))
  1639.             {
  1640.                 l = (pstr) ? strlen(pstr) : 0;
  1641.                 if (data->StartButtonImageFile == NULL  &&  l != 0  ||
  1642.                     data->StartButtonImageFile != NULL  &&
  1643.                         (l == 0  || strcmpi(pstr, data->StartButtonImageFile) != 0))
  1644.                 {
  1645.                     SetStartButtonImageFileName(data, (l) ? pstr : NULL);
  1646.                     running = TRUE;
  1647.                 }
  1648.             }
  1649.  
  1650.             /*
  1651.                 get mines left digits image file and check if updated
  1652.             */
  1653.             if (GetAttr(MUIA_ISWindow_MinesDigitsImage, win, (ULONG *)&pstr))
  1654.             {
  1655.                 l = (pstr) ? strlen(pstr) : 0;
  1656.                 if (data->MinesDigitsImageFile == NULL  &&  l != 0  ||
  1657.                     data->MinesDigitsImageFile != NULL  &&
  1658.                         (l == 0  || strcmpi(pstr, data->MinesDigitsImageFile) != 0))
  1659.                 {
  1660.                     SetMinesDigitsImageFileName(data, (l) ? pstr : NULL);
  1661.                     running = TRUE;
  1662.                 }
  1663.             }
  1664.  
  1665.             /*
  1666.                 get time taken digits image file and check if updated
  1667.             */
  1668.             if (GetAttr(MUIA_ISWindow_TimeDigitsImage, win, (ULONG *)&pstr))
  1669.             {
  1670.                 l = (pstr) ? strlen(pstr) : 0;
  1671.                 if (data->TimeDigitsImageFile == NULL  &&  l != 0  ||
  1672.                     data->TimeDigitsImageFile != NULL  &&
  1673.                         (l == 0  || strcmpi(pstr, data->TimeDigitsImageFile) != 0))
  1674.                 {
  1675.                     SetTimeDigitsImageFileName(data, (l) ? pstr : NULL);
  1676.                     running = TRUE;
  1677.                 }
  1678.             }
  1679.         }
  1680.  
  1681.         /*
  1682.             detach the window from the app and dispose of it
  1683.         */
  1684.         DoMethod(app, OM_REMMEMBER, win);
  1685.         MUI_DisposeObject(win);
  1686.  
  1687.         /*
  1688.             wake up the parent window
  1689.         */
  1690.         SetAttrs(obj, MUIA_Window_Sleep, FALSE, TAG_DONE);
  1691.  
  1692.         /*
  1693.             restore origional current dir
  1694.         */
  1695.         CurrentDir(lock);
  1696.  
  1697.         /*
  1698.             if the imagery was updated the close the window, set the new
  1699.             image files and re-open the window
  1700.         */
  1701.         if (running)
  1702.         {
  1703.             SetAttrs(obj, MUIA_Window_Open, FALSE, TAG_DONE);
  1704.             SetAttrs(data->MineField,
  1705.                         MUIA_MineField_ImageFile, data->MineFieldImageFile,
  1706.                         TAG_DONE);
  1707.             SetAttrs(data->FaceButton,
  1708.                         MUIA_FaceButton_ImageFile, data->StartButtonImageFile,
  1709.                         TAG_DONE);
  1710.             SetAttrs(data->MinesDisp,
  1711.                         MUIA_Digits_ImageFile, data->MinesDigitsImageFile,
  1712.                         TAG_DONE);
  1713.             SetAttrs(data->TimeDisp,
  1714.                         MUIA_Digits_ImageFile, data->TimeDigitsImageFile,
  1715.                         TAG_DONE);
  1716.             SetAttrs(obj, MUIA_Window_Open, TRUE, TAG_DONE);
  1717.         }
  1718.     }
  1719. }
  1720.  
  1721. /*
  1722.     function :      shows the program info window
  1723.  
  1724.     parameters :    obj = pointer to the parent window object
  1725. */
  1726. #define INFO_FMT        "\033c%s\n\n%s\n\n%s%s%s%s%s"
  1727.  
  1728. static void ShowProgInfo(Object * obj)
  1729. {
  1730.     Object *app;
  1731.     STRPTR appDescription, appVersion, appCopyright,
  1732.            strCredits, strTranslator, str1, str2;
  1733.     /*
  1734.         get string pointers for info window
  1735.     */
  1736.     app = _app(obj);
  1737.     DoMethod(app, OM_GET, MUIA_Application_Description, &appDescription);
  1738.     DoMethod(app, OM_GET, MUIA_Application_Version, &appVersion);
  1739.     DoMethod(app, OM_GET, MUIA_Application_Copyright, &appCopyright);
  1740.     strCredits = GetStr(MSG_PROGINFO_CREDITS);
  1741.     strTranslator = GetStr(MSG_PROGINFO_TRANSLATOR);
  1742.     str1 = (*strCredits) ? "\n\n" : "";
  1743.     str2 = (*strTranslator) ? "\n\n" : "";
  1744.  
  1745.     MUI_Request(app, obj, 0, GetStr(MSG_PROGINFO_TITLE),
  1746.                               GetStr(MSG_CONTINUE_GADGET),
  1747.                               INFO_FMT, appVersion + 6,
  1748.                               appDescription, appCopyright,
  1749.                               str1, strCredits,
  1750.                               str2, strTranslator);
  1751. }
  1752.  
  1753.  
  1754. /*
  1755.     function :  create the MFWindow custom class also creating
  1756.                 any child custom classes
  1757.  
  1758.     return :    pointer to the MFWindow custom class if all
  1759.                 the custom classes were successfully created
  1760.                 otherwise NULL
  1761. */
  1762. struct MUI_CustomClass * CreateMFWindowClass(void)
  1763. {
  1764.     if ((mccMineField = CreateMineFieldClass()))
  1765.     {
  1766.         if ((mccFaceButton = CreateFaceButtonClass()))
  1767.         {
  1768.             if ((mccDigits = CreateDigitsClass()))
  1769.             {
  1770.                 if ((mccBTWindow = CreateBTWindowClass()))
  1771.                 {
  1772.                     if ((mccLEWindow = CreateLEWindowClass()))
  1773.                     {
  1774.                         if ((mccISWindow = CreateISWindowClass()))
  1775.                         {
  1776.                             struct MUI_CustomClass * cmfw;
  1777.                             cmfw = MUI_CreateCustomClass(NULL, MUIC_Window, NULL,
  1778.                                                            sizeof(struct MFWindowData),
  1779.                                                            MFWindowDispatcher);
  1780.                             if (cmfw)
  1781.                             {
  1782.                                 return cmfw;
  1783.                             }
  1784.  
  1785.                             DeleteISWindowClass(mccISWindow);
  1786.                             mccISWindow = NULL;
  1787.                         }
  1788.                         DeleteLEWindowClass(mccLEWindow);
  1789.                         mccLEWindow = NULL;
  1790.                     }
  1791.                     DeleteBTWindowClass(mccBTWindow);
  1792.                     mccBTWindow = NULL;
  1793.                 }
  1794.                 DeleteDigitsClass(mccDigits);
  1795.                 mccDigits = NULL;
  1796.             }
  1797.             DeleteFaceButtonClass(mccFaceButton);
  1798.             mccFaceButton = NULL;
  1799.         }
  1800.         DeleteMineFieldClass(mccMineField);
  1801.         mccMineField = NULL;
  1802.     }
  1803.  
  1804.     return NULL;
  1805. }
  1806.  
  1807. /*
  1808.     function :    delete the MFWindow custom class
  1809.  
  1810.     parameters :  mfwc = pointer to the MFWindow custom class to delete
  1811.  
  1812.     return :      none
  1813. */
  1814. void DeleteMFWindowClass(struct MUI_CustomClass * mfwc)
  1815. {
  1816.     if (mfwc)
  1817.     {
  1818.         MUI_DeleteCustomClass(mfwc);
  1819.     }
  1820.  
  1821.     if (mccMineField)
  1822.     {
  1823.         DeleteMineFieldClass(mccMineField);
  1824.         mccMineField = NULL;
  1825.     }
  1826.  
  1827.     if (mccFaceButton)
  1828.     {
  1829.         DeleteFaceButtonClass(mccFaceButton);
  1830.         mccFaceButton = NULL;
  1831.     }
  1832.  
  1833.     if (mccDigits)
  1834.     {
  1835.         DeleteDigitsClass(mccDigits);
  1836.         mccDigits = NULL;
  1837.     }
  1838.  
  1839.     if (mccBTWindow)
  1840.     {
  1841.         DeleteBTWindowClass(mccBTWindow);
  1842.         mccBTWindow = NULL;
  1843.     }
  1844.  
  1845.     if (mccLEWindow)
  1846.     {
  1847.         DeleteLEWindowClass(mccLEWindow);
  1848.         mccLEWindow = NULL;
  1849.     }
  1850.  
  1851.     if (mccISWindow)
  1852.     {
  1853.         DeleteISWindowClass(mccISWindow);
  1854.         mccISWindow = NULL;
  1855.     }
  1856. }
  1857.  
  1858.  
  1859.